package com.iwhalecloud.bss.kite.cucc.service.scene;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import com.iwhalecloud.bss.kite.client.dto.DataResult;
import org.apache.commons.collections.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneFuncProdInstService;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneOfferInstService;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneProdInstService;
import com.iwhalecloud.bss.kite.client.dto.inst.ProdInstDTO;
import com.iwhalecloud.bss.kite.client.dto.spec.in.ContractOfferDetailDTO;
import com.iwhalecloud.bss.kite.client.enums.TriggerStrategy;
import com.iwhalecloud.bss.kite.client.vo.scene.ProdFuncVO;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.util.SeqUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.goods.IGoodsService;
import com.iwhalecloud.bss.kite.cucc.client.api.scene.ICuccSceneTemplateService;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.AttrDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.AttrValuesDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.scene.CuccAttrChgTempDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.scene.CuccOfferObjTempDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.scene.CuccRelChgTempDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.scene.CuccSceneTemplateDTO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.CuccOfferInitVO;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.CuccSceneTemplateVo;
import com.iwhalecloud.bss.kite.cucc.common.util.CommonUtil;
import com.iwhalecloud.bss.kite.cucc.dataservice.entity.AttrChangeTemp;
import com.iwhalecloud.bss.kite.cucc.dataservice.entity.OfferObjTemp;
import com.iwhalecloud.bss.kite.cucc.dataservice.entity.RelChangeTemp;
import com.iwhalecloud.bss.kite.cucc.dataservice.entity.SceneTemplate;
import com.iwhalecloud.bss.kite.cucc.dataservice.mapper.template.scene.CuccAttrChgTempMapper;
import com.iwhalecloud.bss.kite.cucc.dataservice.mapper.template.scene.CuccOfferObjTempMapper;
import com.iwhalecloud.bss.kite.cucc.dataservice.mapper.template.scene.CuccRelChgTempMapper;
import com.iwhalecloud.bss.kite.cucc.dataservice.mapper.template.scene.CuccSceneTemplMapper;
import com.iwhalecloud.bss.kite.cucc.spec.impl.transfer.GoodsInfoTransfer;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.entity.OfferAttr;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.listener.handler.attr.impl.single.IInstConstraintHandler;
import com.iwhalecloud.bss.kite.manager.api.IOperateSceneInstService;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.cache.InstCacheMng;
import com.iwhalecloud.bss.kite.manager.cache.inst.InstChangeCache;
import com.iwhalecloud.bss.kite.manager.cache.inst.RelChangeCache;
import com.iwhalecloud.bss.kite.manager.dto.KiteAttrDTO;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.enums.RelType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteInstChange;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteRelChange;
import com.iwhalecloud.bss.kite.manager.util.RelTypeUtils;
import com.iwhalecloud.bss.kite.service.scene.attr.OperateInstAttrService;
import com.ztesoft.bss.base.staticdata.CoreDataPublic;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.StringUtil;

import tk.mybatis.mapper.entity.Example;

/**
 * @Author: pan.dan
 * @Date: 2020/11/17
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CuccSceneTemplateService implements ICuccSceneTemplateService {

    @Autowired
    IQuerySceneInstService querySceneInstService;

    @Autowired
    IOperateSceneInstService operateSceneInstService;

    @Autowired
    CuccSceneTemplMapper sceneTemplMapper;

    @Autowired
    CuccOfferObjTempMapper offerObjTempMapper;

    @Autowired
    CuccAttrChgTempMapper attrChgTempMapper;

    @Autowired
    CuccRelChgTempMapper relChgTempMapper;

    @Autowired
    private IGoodsService goodsService;

    @Autowired
    private OperateInstAttrService operateInstAttrService;

    @Autowired
    private IOperateSceneFuncProdInstService operateSceneFuncProdInstService;

    @Autowired
    private IOperateSceneOfferInstService operateSceneOfferInstService;

    @Autowired
    private IOperateSceneProdInstService operateSceneProdInstService;

    /**
     * 保存模版
     */
    @Override
    public String saveTemplate(String sceneInstId, String templName) {
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        KiteOfferInst offerInst = querySceneInstService.getOfferInst(sceneInst.getCustId(), sceneInst.getRootInstId());

        //保存scene_template表数据
        CuccSceneTemplateDTO sceneTemplateDTO = new CuccSceneTemplateDTO();
        String sceneTemplId = SeqUtils.getNext("seq_scene_template_scene_templ_id");
        sceneTemplateDTO.setSceneTemplId(sceneTemplId);
        sceneTemplateDTO.setSceneTemplName(templName);
        sceneTemplateDTO.setRootInstId(sceneInst.getRootInstId());
        sceneTemplateDTO.setOfferId(offerInst.getOfferId());
        sceneTemplateDTO.setStaffId(Long.toString(ContextUtil.getLoginStaffId()));
        sceneTemplateDTO.setCreateDate(LocalDateTime.now());
        sceneTemplateDTO.setStatusCd(CoreDataPublic.PUB_C_0001_1000);

        saveOfferObjTemp(sceneInst, sceneTemplId);
        saveAttrChange(sceneInst, sceneTemplId);
        saveRelChange(sceneInst, sceneTemplId);

        int ret = sceneTemplMapper.insertSceneTempl(Arrays.asList(sceneTemplateDTO));
        if (ret < 1) {
            return null;
        }

        return sceneTemplId;
    }

    private boolean saveOfferObjTemp(KiteSceneInst sceneInst, String sceneTemplId) {
        Map<String, List<KiteInstChange>> instChangeMap = InstChangeCache.get(sceneInst.getSceneInstId());
        if (Objects.isNull(instChangeMap)) {
            return false;
        }

        List<CuccOfferObjTempDTO> offerObjTempList = new ArrayList<>();
        List<String> addList = new ArrayList<>();
        instChangeMap.forEach((key, instChange) -> {
            if (KiteListUtils.isEmpty(instChange)) {
                return;
            }
            KiteInst inst = querySceneInstService.getKiteInst(sceneInst.getCustId(), instChange.get(0).getInstType(), instChange.get(0).getInstId());
            //校验唯一性，避免多次保存同一个实例
            if (addList.contains(inst.getInstId())) {
                return;
            }
            CuccOfferObjTempDTO offerObjTemp = new CuccOfferObjTempDTO();
            offerObjTemp.setInstId(inst.getInstId());
            offerObjTemp.setSpecId(inst.getSpecId());
            offerObjTemp.setInstType(inst.getInstType());
            offerObjTemp.setSceneTemplId(sceneTemplId);
            offerObjTemp.setObjTempId(SeqUtils.getNext("seq_offer_obj_temp_obj_temp_id"));

            addList.add(inst.getInstId());
            offerObjTempList.add(offerObjTemp);
        });
        offerObjTempMapper.insertOfferObjTemp(offerObjTempList);

        return true;
    }

    private boolean saveAttrChange(KiteSceneInst sceneInst, String sceneTemplId) {
        Map<String, List<KiteInstChange>> instChangeMap = InstChangeCache.get(sceneInst.getSceneInstId());

        if (Objects.isNull(instChangeMap)) {
            return false;
        }

        // 模板保存，不保存关键属性（2022-04-07需求）
        List<String> keyAttrs = new ArrayList<>();
        KiteOfferInst offerInst = querySceneInstService.getOfferInst(sceneInst.getCustId(), sceneInst.getRootInstId());
        String saleGoodsCode = offerInst.getAttrValue("saleGoodsCode");
        if(KiteStringUtils.isNotEmpty(saleGoodsCode)) {
            DataResult<List<AttrDTO>> result =  goodsService.queryGoodKeyAttrsByProvince(saleGoodsCode);
            if(Objects.nonNull(result)) {
                List<AttrDTO> attrs = result.getResultObject();
                if(KiteListUtils.isNotEmpty(attrs)) {
                    attrs.forEach(attr -> keyAttrs.add(attr.getAttrCode()));
                }
            }
        }

        List<CuccAttrChgTempDTO> attrChgTempList = new ArrayList<>();
        instChangeMap.forEach((key, instChange) -> {
            if (KiteListUtils.isEmpty(instChange)) {
                return;
            }
            KiteInst inst = querySceneInstService.getKiteInst(sceneInst.getCustId(), instChange.get(0).getInstType(), instChange.get(0).getInstId());
            Map<String, KiteAttr> attrMap = inst.getAttrMap();

            attrMap.forEach((fieldName, attr) -> {
                if(KiteStringUtils.equals(fieldName,"historyData") || keyAttrs.contains(fieldName)) {
                    return;
                }
                CuccAttrChgTempDTO attrChgTempDTO = new CuccAttrChgTempDTO();
                attrChgTempDTO.setAttrChgId(SeqUtils.getNext("seq_attr_change_temp_attr_chg_id"));
                attrChgTempDTO.setInstId(inst.getInstId());
                attrChgTempDTO.setSpecId(inst.getSpecId());
                attrChgTempDTO.setInstType(inst.getInstType());
                attrChgTempDTO.setFieldName(attr.getFieldName());
                attrChgTempDTO.setFieldValue(Optional.ofNullable(attr.getValue()).orElse(attr.getDefaultValue()));
                attrChgTempDTO.setSceneTemplId(sceneTemplId);

                attrChgTempList.add(attrChgTempDTO);
            });
        });
        attrChgTempMapper.insertAttrChgTemp(attrChgTempList);

        return true;
    }

    private boolean saveRelChange(KiteSceneInst sceneInst, String sceneTemplId) {
        Map<String, List<KiteRelChange>> relChangeMap = RelChangeCache.get(sceneInst.getSceneInstId());
        if (Objects.isNull(relChangeMap)) {
            return false;
        }

        List<CuccRelChgTempDTO> relChgTempList = new ArrayList<>();
        relChangeMap.forEach((key, relChgList) -> {
            if (KiteListUtils.isEmpty(relChgList)) {
                return;
            }
            for (KiteRelChange rel: relChgList) {
                CuccRelChgTempDTO relChgTempDTO = new CuccRelChgTempDTO();
                relChgTempDTO.setRelChgId(SeqUtils.getNext("seq_rel_change_temp_rel_chg_id"));
                relChgTempDTO.setAInstId(rel.getSourceInstId());
                relChgTempDTO.setASpecId(InstCacheMng.getInst(rel.getSourceInstType(), rel.getSourceInstId(), sceneInst.getCustId()).getSpecId());
                relChgTempDTO.setAInstType(rel.getSourceInstType());
                relChgTempDTO.setZInstId(rel.getTargetInstId());
                relChgTempDTO.setZSpecId(InstCacheMng.getInst(rel.getTargetInstType(), rel.getTargetInstId(), sceneInst.getCustId()).getSpecId());
                relChgTempDTO.setZInstType(rel.getTargetInstType());
                relChgTempDTO.setRelType(((RelType) rel.getRelType()).name());
                relChgTempDTO.setActionType(rel.getNewActionType());
                relChgTempDTO.setSceneTemplId(sceneTemplId);

                relChgTempList.add(relChgTempDTO);
            }
        });
        relChgTempMapper.insertRelChgTemp(relChgTempList);

        return true;
    }

    /**
     * 更新模版
     */
    public String updateTemplate(String sceneInstId, String templName, String sceneTemplId) {
        deleteTemplDetail(sceneTemplId);

        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        saveOfferObjTemp(sceneInst, sceneTemplId);
        saveAttrChange(sceneInst, sceneTemplId);
        saveRelChange(sceneInst, sceneTemplId);

        sceneTemplMapper.updateSceneTempById(templName, sceneInst.getRootInstId(), sceneTemplId);

        return sceneTemplId;
    }

    /**
     * 删除模版
     */
    @Override
    public boolean deleteTemplate(String sceneTemplId) {
        deleteTemplDetail(sceneTemplId);
        int i = sceneTemplMapper.deleteByPrimaryKey(sceneTemplId);
        if (i < 1) {
            return false;
        }
        return true;
    }

    /**
     * 删除模版明细
     */
    private void deleteTemplDetail(String sceneTemplId) {
        Example example = new Example(OfferObjTemp.class);
        example.createCriteria().andEqualTo("sceneTemplId", sceneTemplId);
        offerObjTempMapper.deleteByExample(example);

        example = new Example(AttrChangeTemp.class);
        example.createCriteria().andEqualTo("sceneTemplId", sceneTemplId);
        attrChgTempMapper.deleteByExample(example);

        example = new Example(RelChangeTemp.class);
        example.createCriteria().andEqualTo("sceneTemplId", sceneTemplId);
        relChgTempMapper.deleteByExample(example);
    }

    /**
     * 模版重命名
     */
    @Override
    public boolean renameTemplate(String sceneTemplId, String newName) {
        int i = sceneTemplMapper.updateTempNameById(newName, sceneTemplId);
        if (i < 1) {
            return false;
        }
        return true;
    }

    /**
     * 根据工号查询所有模版
     */
    public PageInfo<CuccSceneTemplateVo> listSceneTempl(String staffId, Integer pageSize, Integer pageIndex) {
        PageHelper.startPage(pageIndex, pageSize);
        List<CuccSceneTemplateVo> list = sceneTemplMapper.selectTemplByStaffId(staffId);
        PageInfo<CuccSceneTemplateVo> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }

    /**
     * 根据工号及当前场景查询属性模版
     */
    public List<CuccSceneTemplateVo> listAttrTempl(String staffId, String sceneInstId) {
        List<CuccSceneTemplateVo> result = new ArrayList<>();
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        String goodsSpu = querySceneInstService.getOfferInst(sceneInst.getCustId(), sceneInst.getRootInstId()).getOfferId();

        List<CuccSceneTemplateVo> allTempllist = sceneTemplMapper
            .selectAttrTemplByStaffAndOffer(staffId, goodsSpu); //根据spu及工号筛选模版
        List<KiteOfferInst> mainOfferInsts = querySceneInstService
            .listInsts(sceneInstId, Arrays.asList(InstType.MAIN_OFFER_INST, InstType.GIFT_OFFER_INST));
        //筛选出当前场景的sku（排除附加产品）
        mainOfferInsts.removeIf(mainOfferInst -> GoodsInfoTransfer.isAddRoleOffer(mainOfferInst.getSpecId(), Optional.ofNullable(mainOfferInst.getAttr("cateId")).map(KiteAttr::getDefaultValue).orElse("")));
        List<String> sceneSkus = new ArrayList<>();
        List<String> prodIds = new ArrayList<>();
        mainOfferInsts.forEach(mainOfferInst -> {
            Offer offer = OfferCache.get(mainOfferInst.getOfferId());
            List<Map<String, Object>> productCategroy = (List<Map<String, Object>>)offer.getOfferMap().get("productCategroy");
            productCategroy.forEach(prodCate -> {
                if ("base".equals(prodCate.get("productType"))) {
                    List<Map<String, Object>> prods = (List<Map<String, Object>>)prodCate.get("products");
                    prods.forEach(prod -> prodIds.add(prod.get("productCode").toString()));
                }
            });

            sceneSkus.add(mainOfferInst.getOfferId());
        });
        sceneSkus.sort((s1, s2) -> (Integer.valueOf(s2.hashCode()).compareTo(Integer.valueOf(s1.hashCode()))));

        //根据模版的主套餐与sku是否匹配，再次筛选模版
        for (CuccSceneTemplateVo templ: allTempllist) {
            List<String> templSkus = new ArrayList<>();
            List<CuccOfferObjTempDTO> offerObjInsts = offerObjTempMapper
                .selectInstByTemplIdAndType(templ.getSceneTemplId(), InstType.MAIN_OFFER_INST.name());
            offerObjInsts.addAll(offerObjTempMapper
                .selectInstByTemplIdAndType(templ.getSceneTemplId(), InstType.GIFT_OFFER_INST.name()));
            for (CuccOfferObjTempDTO inst : offerObjInsts) {
                String cateId = attrChgTempMapper.selectAttrValueByInstId(templ.getSceneTemplId(), inst.getInstId(), "cateId");
                if (StringUtil.isNotEmpty(cateId) && GoodsInfoTransfer.isAddRoleOffer(inst.getSpecId(), cateId)) {
                    continue;
                }
                templSkus.add(inst.getSpecId());
            }
            templSkus.sort((s1, s2) -> (Integer.valueOf(s2.hashCode()).compareTo(Integer.valueOf(s1.hashCode()))));
            if (ListUtils.isEqualList(templSkus, sceneSkus)) {
                result.add(templ);
            }
        }
        operateSceneInstService.putExtParameter(sceneInstId, "keyOfferIds", goodsSpu + "," + sceneSkus + "," + prodIds);

        return result;
    }

    private Map<String, String> createInstIdMap(String sceneTemplId, String sceneInstId) {
        //模版所有成员实例
        List<CuccOfferObjTempDTO> offerObjInsts = offerObjTempMapper.selectOfferObjInstByTemplId(sceneTemplId);
        //顺序：主套餐，促销，产品，功能产品
        //把功能产品排在最后，避免接入产品实例还没创建时创建功能产品实例
        offerObjInsts.sort(Comparator.comparing(inst -> inst.getInstType()));

        Map<String, String> instIdMap = new HashMap<>(); //建立实例id与模版之间的对应关系(key, value)->(模版中的实例id，场景中的实例id)

        for (CuccOfferObjTempDTO templInst: offerObjInsts) {
            List<KiteInst> insts = querySceneInstService.listInsts(sceneInstId, Arrays.asList(templInst.getInstType()), templInst.getSpecId());
            //场景中存在该模版实例，建立对应
            if (KiteListUtils.isNotEmpty(insts)) {
                //场景中存在一个或多个该模版实例
                for (KiteInst inst: insts) {
                    //如果场景中该实例未建立过对应关系，就与该模版实例建立
                    if (!instIdMap.values().contains(inst.getInstId())) {
                        instIdMap.put(templInst.getInstId(), inst.getInstId());
                        break;
                    }
                }
                //场景中同规格的实例已经建立关联（模版中同规格的实例，比场景中多），需要新建实例
                if (!instIdMap.keySet().contains(templInst.getInstId())) {
                    String newInstId = createKiteInstByTempl(sceneInstId, templInst, instIdMap);
                    instIdMap.put(templInst.getInstId(), newInstId);
                }
            }
            //场景中不存在该模版实例，创建实例，再建立对应
            else {
                String newInstId = createKiteInstByTempl(sceneInstId, templInst, instIdMap);
                instIdMap.put(templInst.getInstId(), newInstId);
            }
        }
        return instIdMap;
    }

    private String createKiteInstByTempl(String sceneInstId, CuccOfferObjTempDTO templInst, Map<String, String> instIdMap) {
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);

        KiteInst inst = new KiteInst();
        inst.setInstType(templInst.getInstType());
        inst.setSpecId(templInst.getSpecId());

        String newInstId = null;
        if (Objects.equals(InstType.PROD_INST, templInst.getInstType())) {
            //附加产品中的产品实例，会在创建主套餐时一起创建，此时目前只会用于创建资费计划产品
            List<KiteOfferInst> mainOfferInst = querySceneInstService.listMainOfferInsts(sceneInstId);
            mainOfferInst.removeIf(offerInst -> GoodsInfoTransfer.isAddRoleOffer(offerInst.getSpecId(), Optional.ofNullable(offerInst.getAttr("cateId")).map(KiteAttr::getDefaultValue).orElse("")));

            ProdInstDTO prodInstDTO = operateSceneProdInstService.addProdRole(sceneInstId, ContextUtil.getUserId().toString(),
                sceneInst.getCustId(), mainOfferInst.get(0).getOfferInstId(), templInst.getSpecId(), "72000007", "", null, "");
            return prodInstDTO.getProdInstId();
        }
        else if (Objects.equals(InstType.MAIN_OFFER_INST, templInst.getInstType()) || Objects.equals(InstType.PROMOTION_OFFER_INST, templInst.getInstType())) {
            //主要新增附加产品
            String roleId = null;
            List<OfferAttr> offerAttrs = OfferCache.get(templInst.getSpecId()).listOfferAttrs().stream()
                .filter(attr -> "cateId".equals(attr.getFieldName())).collect(Collectors.toList());
            if (!KiteListUtils.isEmpty(offerAttrs)) {
                roleId = offerAttrs.get(0).getDefaultValue();
            }
            KiteOfferInst kiteOfferInst = operateSceneOfferInstService.addOfferInst(sceneInstId, sceneInst.getRootInstId(), templInst.getSpecId(), roleId, sceneInst.getCustId(), ContextUtil.getUserId().toString()).getResultObject();
            return kiteOfferInst.getOfferInstId();
        }
        else if (Objects.equals(InstType.ADDITIONAL_OFFER_INST, templInst.getInstType())) {
            //主要新增资费产品（可选包）

        }
        else if (Objects.equals(InstType.PROD_INST_FUNC, templInst.getInstType())) {
            //主要新增APN，5G切片，通信计划等功能产品
            operateSceneInstService.putExtParameter(sceneInstId, IInstConstraintHandler.KEY_IF_EXECUTE, Boolean.TRUE);
            String accessProdInstId = relChgTempMapper.selectAccProdByFuncInst(templInst.getSceneTemplId(), templInst.getInstId());
            ProdFuncVO kiteProdFuncInst = operateSceneFuncProdInstService.addFuncProdInst(sceneInstId, instIdMap.get(accessProdInstId), templInst.getSpecId(), sceneInst.getCustId(), sceneInst.getStaffId()).getResultObject();
            return kiteProdFuncInst.getProdInstId();
        }
        return newInstId;
    }

//    private String createKiteInstByTempl (String sceneInstId, CuccOfferObjTempDTO templInst, Map<String, String> instIdMap) {
//        KiteInst inst = new KiteInst();
//        inst.setInstType(templInst.getInstType());
//        inst.setSpecId(templInst.getSpecId());
//        //inst.setSpecName(OfferCache.get(templInst.getSpecId()).getOfferName());
//
//        List<KiteAttr> kiteAttrs = new ArrayList<KiteAttr>();
//        String newInstId = null;
//        if (Objects.equals(InstType.PROD_INST, templInst.getInstType())) {
//            KiteProdInst prodInst = KiteBeanUtils.transform(inst, KiteProdInst.class);
//            operateInstAttrService.initProductAttr(prodInst, kiteAttrs, ProductCache.get(prodInst.getSpecId()).listProdAttrs());
//            newInstId = operateSceneInstService.addInst(sceneInstId, prodInst);
//
//        }
//        else if (Objects.equals(InstType.MAIN_OFFER_INST, templInst.getInstType()) || Objects.equals(InstType.PROMOTION_OFFER_INST, templInst.getInstType()) || Objects.equals(InstType.ADDITIONAL_OFFER_INST, templInst.getInstType())) {
//            KiteOfferInst offerInst = KiteBeanUtils.transform(inst, KiteOfferInst.class);
//            operateInstAttrService.initOfferAttr(offerInst, kiteAttrs, OfferCache.get(offerInst.getSpecId()).listOfferAttrs());
//            newInstId = operateSceneInstService.addInst(sceneInstId, offerInst);
//        }
//        else if (Objects.equals(InstType.PROD_INST_FUNC, templInst.getInstType())) {
//            KiteProdInstFunc prodFuncInst = KiteBeanUtils.transform(inst, KiteProdInstFunc.class);
//            operateInstAttrService.initProdInstFuncAttr(prodFuncInst, kiteAttrs, ProductCache.get(prodFuncInst.getSpecId()).listProdAttrs());
//            String accProdInTempl = relChgTempMapper.selectAccProdByFuncInst(templInst.getSceneTemplId(), templInst.getInstId());
//            prodFuncInst.setAccProdInstId(instIdMap.get(accProdInTempl));
//            newInstId = operateSceneInstService.addInst(sceneInstId, prodFuncInst);
//        }
//        return newInstId;
//    }

    /**
     * 根据模版还原场景
     * 执行先删后增
     * @param sceneTemplId
     * @param sceneInstId
     */
    public void updateSceneByTempl(String sceneTemplId, String sceneInstId) {
        operateSceneInstService.putExtParameter(sceneInstId, "sceneTempl", sceneTemplId);
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        String keyOfferIds = querySceneInstService.getExtParameterValue(sceneInstId, "keyOfferIds");
        String custId = sceneInst.getCustId();

        //非场景基础实例（促销，主套餐，主产品），都删掉（包括关系）
        List<KiteInst> insts = querySceneInstService.listInsts(sceneInstId, Arrays.asList(InstType.PROD_INST_FUNC, InstType.PROD_INST, InstType.ADDITIONAL_OFFER_INST, InstType.MAIN_OFFER_INST, InstType.PROMOTION_OFFER_INST));
        List<KiteInst> deleteInsts = new ArrayList<>();
        insts.forEach(inst -> {
            if (!keyOfferIds.contains(inst.getSpecId())) {
                deleteInsts.add(inst);
            }
        });

        operateSceneInstService.removeInst(sceneInstId, custId, deleteInsts);

        //建立对应关系（新增实例，初始化属性，新增关系）
        Map<String, String> instIdMap = createInstIdMap(sceneTemplId, sceneInstId);

        //还原模版所有属性变动
        updateAttrByTempl(instIdMap, sceneTemplId, sceneInstId);

        //还原模版所有关系变动
        List<CuccRelChgTempDTO> relChgList = relChgTempMapper.selectRelChgByTempId(sceneTemplId);
        for (CuccRelChgTempDTO relChg : relChgList) {
            //获取关系A端
            KiteInst aInst = querySceneInstService
                .getKiteInst(custId, relChg.getAInstType(), instIdMap.get(relChg.getAInstId()));
            //获取关系Z端
            KiteInst zInst = querySceneInstService
                .getKiteInst(custId, relChg.getZInstType(), instIdMap.get(relChg.getZInstId()));
            //添加关系
            if (RelType.OFFER_OBJ_REL_TYPE_120000.equals(RelTypeUtils.getRelType(relChg.getRelType()))) {
                operateSceneInstService
                    .addInstRel(sceneInstId, aInst.getInstType(), aInst.getInstId(), zInst.getInstType(),
                        zInst.getInstId(), RelTypeUtils.getRelType(relChg.getRelType()), relChg.getActionType());
            }
        }
    }

    /**
     * 根据模版还原属性
     *
     * @param sceneTemplId
     * @param sceneInstId
     */
    public void updateAttrByTempl(Map<String, String> instIdMap, String sceneTemplId, String sceneInstId) {
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);

        //还原模版所有属性变动
        List<CuccAttrChgTempDTO> attrChgList = attrChgTempMapper.selectAttrChgByTempId(sceneTemplId); //已按照实例id排序
        if (KiteListUtils.isEmpty(attrChgList)) {
            return;
        }
        //将属性进行分组，然后进行属性值还原
        Map<String, List<CuccAttrChgTempDTO>> attrChangeMap = attrChgList.stream().collect(Collectors.groupingBy(CuccAttrChgTempDTO::getInstId));
        for(Map.Entry<String, List<CuccAttrChgTempDTO>> entry : attrChangeMap.entrySet()){
            String mapKey = entry.getKey();
            List<CuccAttrChgTempDTO> mapValue = entry.getValue();
            String instId = instIdMap.get(mapKey);
            if (KiteStringUtils.isEmpty(instId)) {
                continue;
            }
            if (KiteListUtils.isEmpty(mapValue)) {
                continue;
            }
            KiteInst inst = querySceneInstService.getKiteInst(sceneInst.getCustId(), mapValue.get(0).getInstType(), instId);
            List<KiteAttr> attrs = KiteListUtils.isNotEmpty(inst.listAttrs()) ? inst.listAttrs() : new ArrayList<>();

            // 只有产品和功能产品属性进行排序
            if (KiteStringUtils.equalsAny(inst.getInstType().name(), InstType.PROD_INST.name(),InstType.PROD_INST_FUNC.name())) {
                //先过滤掉orderId为null的数据
                attrs.removeIf(kiteAttr -> KiteStringUtils.isEmpty(kiteAttr.getOrderId()));
                attrs.sort(
                    (o1, o2) -> Integer.parseInt(o1.getOrderId())
                        - Integer.parseInt(o2.getOrderId()));
            }

            //  需要按照属性的排序进行属性值还原，否则属性界面展示属性不对
            for (KiteAttr instAttr : attrs) {
              //APN标识，5G切片编码，通信计划标识，资费计划名称不做还原资费计划标识不回填
                if (!KiteStringUtils.equalsAny(instAttr.getFieldName(), "200004135","200004157","200004128","200003698","200004145","200004146","200004129","userInstId")
                    && !instAttr.getFieldName().startsWith("attrGroupInstId_")) {
                    CuccAttrChgTempDTO attrChg = mapValue.stream().filter(mapAttr -> KiteStringUtils.isEqual(instAttr.getFieldName(), mapAttr.getFieldName())).findFirst().orElse(null);
                    if (Objects.nonNull(attrChg)) {
                        // 还原属性值时，需要对APN通信计划、APN资费计划属性做特殊处理
                        if (KiteStringUtils.equalsAny(instAttr.getFieldName(), "200004034","200003728") && KiteStringUtils.isNotEmpty(attrChg.getFieldValue())) {
                            List<String> apnValues = Arrays.asList(attrChg.getFieldValue().split(","));
                            List<String> newApnValues = new ArrayList<>();
                            for (String apnValue : apnValues) {
                                CuccAttrChgTempDTO attrChange = attrChgList.stream().filter(changeAttr -> KiteStringUtils.isEqual(changeAttr.getFieldName(), "200004135") && KiteStringUtils.isEqual(changeAttr.getFieldValue(), apnValue)).findFirst().orElse(null);
                                if (Objects.nonNull(attrChange)) {
                                    KiteInst apnInst = querySceneInstService.getKiteInst(sceneInst.getCustId(), attrChange.getInstType(), instIdMap.get(attrChange.getInstId()));
                                    // 对应的APN属性的APN标识：将APN标识的值设置为通信计划的APN通信计划属性以及资费计划的APN资费计划属性
                                    KiteAttr newApnAttr = apnInst.listAttrs().stream().filter(apnAttr -> KiteStringUtils.isEqual(apnAttr.getFieldName(), "200004135")).findFirst().orElse(null);
                                    if (Objects.nonNull(newApnAttr)) {
                                        newApnValues.add(newApnAttr.getValue());
                                    }
                                    else {
                                        newApnValues.add(apnValue);
                                    }
                                }
                                else {
                                    newApnValues.add(apnValue);
                                }
                            }
                            if (KiteListUtils.isNotEmpty(newApnValues)) {
                                operateInstAttrService.setAttrValue(inst, attrChg.getFieldName(), String.join(",", newApnValues), sceneInstId, CommonUtil.getAttrDataJsonOfLoadTmpl(TriggerStrategy.LOAD_TMPL));
                            }

                        }
                        else {
                            operateInstAttrService.setAttrValue(inst, attrChg.getFieldName(), attrChg.getFieldValue(), sceneInstId, CommonUtil.getAttrDataJsonOfLoadTmpl(TriggerStrategy.LOAD_TMPL));
                        }
                    }
                }

            }
        }

    }

    /**
     * 还原商品关键属性
     *
     * @param offerId
     * @param sceneTemplId
     */
    private List<KiteAttrDTO> getKeyAttrValue(String offerId, String sceneTemplId) {
        List<AttrDTO> listKeyAttr= goodsService.queryGoodKeyAttrs(offerId).getResultObject();

        List<KiteAttrDTO> kiteListKeyAttr= new ArrayList<>();
        for (AttrDTO keyAttr: listKeyAttr) {
            String attrValue = attrChgTempMapper.selectAttrValueInTempl(sceneTemplId, keyAttr.getAttrCode());
            String valueDesc = keyAttr.getAttrValCodes();
            //目前默认关键属性全部都配有下拉值
            List<AttrValuesDTO> attrValues = keyAttr.getAttrValues();
            if (KiteListUtils.isNotEmpty(attrValues)) {
                for (AttrValuesDTO attrvalue: attrValues) {
                    if (StringUtil.equals(attrvalue.getValueCode(), attrValue)) {
                        valueDesc = attrvalue.getValueName();
                        break;
                    }
                }
            }
            KiteAttrDTO attr = new KiteAttrDTO();
            attr.setFieldName(keyAttr.getAttrCode());
            attr.setValue(attrValue);
            attr.setValueDesc(valueDesc);
            kiteListKeyAttr.add(attr);
        }
        return kiteListKeyAttr;
    }

    /**
     * 还原场景初始化入参offerVo
     *
     * @param sceneTemplId
     */
    public CuccOfferInitVO getTemplOfferVo(String sceneTemplId) {
        CuccOfferInitVO offerVo = new CuccOfferInitVO();
        //获取模版
        SceneTemplate templ = sceneTemplMapper.selectByPrimaryKey(sceneTemplId);
        //获取模版成员实例
        List<CuccOfferObjTempDTO> offerObjInsts = offerObjTempMapper.selectOfferObjInstByTemplId(sceneTemplId);

        //构造singleOffers，取模版中所有main_offer_inst
        //TODO 还未筛选掉附加产品
        List<ContractOfferDetailDTO> singleOffers = new ArrayList<>();
        for (CuccOfferObjTempDTO objInst: offerObjInsts) {
            if (Objects.equals(objInst.getInstType(), InstType.MAIN_OFFER_INST)) {
                ContractOfferDetailDTO offerDetail = new ContractOfferDetailDTO();
                offerDetail.setAttrs(getKeyAttrValue(templ.getOfferId(), sceneTemplId));
                offerDetail.setOfferId(objInst.getSpecId());
                singleOffers.add(offerDetail);
            }
        }
        offerVo.setSingleOffers(singleOffers);
        offerVo.setOfferId(templ.getOfferId());
        offerVo.setServiceOfferId(ServiceOfferConsts.SERVICE_OFFER_ORDER);

        return offerVo;
    }
}
